package utils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Mr.Sun
 * @date 2022年02月20日 11:45
 *
 * 递归计数：
 * 使用Class.isAssignableFrom(), 创建一个不限于类型计数的通用工具
 */
public class TypeCounter extends HashMap<Class<?>,Integer> {
    private Class<?> baseType;

    public TypeCounter(Class<?> baseType) {
        this.baseType = baseType;
    }

    public void count(Object obj) {
        Class<?> type = obj.getClass();
        // 使用Class.isAssignableFrom() 执行运行时检查
        // 以检验你传递的对象确实属于我们感兴趣的继承结构
        if(!baseType.isAssignableFrom(type))
            throw new RuntimeException(obj + " incorrect type: "
                    + type + ", should be type or subtype of "
                    + baseType);
        countClass(type);
    }

    private void countClass(Class<?> type) {
        // 1.首先对该类的确切类型计数
        Integer quantity = get(type);
        put(type, quantity == null ? 1 : quantity + 1);
        // 2.如果其父类可以赋值给baseType, countClass()将其超类上递归计数
        Class<?> superClass = type.getSuperclass();
        if(superClass != null &&
                baseType.isAssignableFrom(superClass))
            countClass(superClass);
    }

    public String toString() {
        StringBuilder result = new StringBuilder("{");
        for(Map.Entry<Class<?>,Integer> pair : entrySet()) {
            result.append(pair.getKey().getSimpleName());
            result.append("=");
            result.append(pair.getValue());
            result.append(", ");
        }
        result.delete(result.length()-2, result.length());
        result.append("}");
        return result.toString();
    }
}
